#include "softupdatepwm.h"

SoftUpdatePwm::SoftUpdatePwm()
{
}

SoftUpdatePwm::~SoftUpdatePwm()
{
}

void SoftUpdatePwm::AttachTimer(SOC_Timer *timer)
{
    DettachTimer();
    m_timer = timer;
    if(m_timer)
    { 
        SetPeriodNoTimer(m_timer->GetPeriod()); //同步period
        m_timer->SetElapsedCallBack([=](auto &sender){
            FW_UNUSED(sender);
            TimerHandler();
        });
    }
    else
    {
        SetPeriodNoTimer(0); 
    }
}

void SoftUpdatePwm::DettachTimer()
{
    if(m_timer == nullptr)
        return;
    
    Stop();
    m_timer->SetElapsedCallBack(nullptr);
    m_timer = nullptr;
}

void SoftUpdatePwm::AttachGpio(const GpioPortPin &gpio, const GpioPortPin &gpioN)
{
    m_pwmItem.AttachGpio(gpio, gpioN);
}

void SoftUpdatePwm::DettachGpio()
{
    m_pwmItem.DettachGpio();
}

void SoftUpdatePwm::Config(bool isReverse, int normalValue, bool isSameWhenNormal)
{
    m_pwmItem.IsReverse = isReverse;
    m_pwmItem.NormalValue = normalValue;
    m_pwmItem.IsSameWhenNormal = isSameWhenNormal;
}

void SoftUpdatePwm::SetFinishedCallback(const PWM_FINISHED_CALLBACK &&func)
{
    m_finishedCallback = func;
}

void SoftUpdatePwm::SetPeriod(int period)
{
    if(m_timer == nullptr)
        return;

    m_timer->SetPeriod(period);
    SetPeriodNoTimer(period);
}

int SoftUpdatePwm::GetPeriod()
{
    return m_timerPeriod;
}

void SoftUpdatePwm::SetDuty(int duty)
{
    m_pwmItem.Duty = duty;
    
    // m_timer->StopBase_IT();
    m_pwmItem.Update();
    // m_timer->StartBase_IT();
}

int SoftUpdatePwm::GetDuty()
{
    return m_pwmItem.Duty;
}

bool SoftUpdatePwm::IsRunning()
{
    return m_pwmItem.IsRunning;
}

void SoftUpdatePwm::Start()
{
    if(m_timer == nullptr)
        return;
    if(m_pwmItem.IsRunning)
        return;
    
    //check
    if(!m_pwmItem.Check())
        return;

    //it is okay
    m_pwmItem.Begin();
    m_timer->StartBase_IT();
}

void SoftUpdatePwm::Stop()
{
    if(m_timer == nullptr)
        return;
    
    if(!m_pwmItem.IsRunning)
        return;

    //先关闭IT
    m_timer->StopBase_IT();
    m_pwmItem.End();
}

void SoftUpdatePwm::TimerHandler()
{
    int next = m_pwmItem.Next();
    m_nextPointUs = next;
    // m_timer->SetTimerCount(0);  //不设置计数为0，误差更小
    m_timer->SetPeriod(next);
    if(m_finishedCallback && m_pwmItem.IsFinishedPoint()) //finished point
    {
        m_finishedCallback(*this); 
    }

    m_prevPointUs = next;
}

void SoftUpdatePwm::SetPeriodNoTimer(int period)
{
    m_timerPeriod = period;
    m_pwmItem.Period = m_timerPeriod;
}
